package club.babyf.nativeai.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * JsonCustomUtil.
 *
 * @author zhanglei.
 * @date 2025/2/27 10:00.
 * @description Jackson JSON 序列化/反序列化工具类
 * 线程安全，基于ObjectMapper线程安全实现
 */
public class JsonCustomUtil {

    private static final ObjectMapper mapper = createMapper();

    private JsonCustomUtil() {
        // 防止实例化
    }

    /**
     * 创建并配置ObjectMapper实例
     */
    private static ObjectMapper createMapper() {
        // 创建ObjectMapper实例
        ObjectMapper mapper = new ObjectMapper();
        // 注册Java8时间模块
        mapper.registerModule(new JavaTimeModule());
        // 美化输出
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        // 空对象不抛异常
        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        // 返回值
        return mapper;
    }

    /**
     * 获取原始ObjectMapper实例（用于特殊配置）
     */
    public static ObjectMapper getMapper() {
        return mapper;
    }

    /* 序列化方法组 */

    /**
     * 对象转JSON字符串
     *
     * @param object 要序列化的对象
     * @return JSON字符串
     * @throws RuntimeException 包装Jackson异常
     */
    public static String toJsonString(Object object) {
        try {
            return mapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON序列化失败", e);
        }
    }

    /**
     * 对象转美化格式JSON字符串
     *
     * @param object 要序列化的对象
     * @return 格式化后的JSON字符串
     */
    public static String toPrettyJsonString(Object object) {
        try {
            return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON美化序列化失败", e);
        }
    }

    /**
     * 对象转JSON字节数组
     *
     * @param object 要序列化的对象
     * @return JSON字节数组
     */
    public static byte[] toJsonBytes(Object object) {
        try {
            return mapper.writeValueAsBytes(object);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON字节序列化失败", e);
        }
    }

    /**
     * 将对象序列化到输出流
     *
     * @param out    目标输出流
     * @param object 要序列化的对象
     * @throws IOException 流操作异常
     */
    public static void writeToStream(OutputStream out, Object object) throws IOException {
        mapper.writeValue(out, object);
    }

    /**
     * 将对象序列化到文件
     *
     * @param file   目标文件
     * @param object 要序列化的对象
     * @throws IOException 文件操作异常
     */
    public static void writeToFile(File file, Object object) throws IOException {
        mapper.writeValue(file, object);
    }

    /* 反序列化方法组 */

    /**
     * JSON字符串转对象
     *
     * @param json  JSON字符串
     * @param clazz 目标类
     * @return 反序列化后的对象
     * @throws RuntimeException 包装Jackson异常
     */
    public static <T> T parse(String json, Class<T> clazz) {
        try {
            return mapper.readValue(json, clazz);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON反序列化失败", e);
        }
    }

    /**
     * JSON字节数组转对象
     *
     * @param bytes JSON字节数组
     * @param clazz 目标类
     * @return 反序列化后的对象
     */
    public static <T> T parse(byte[] bytes, Class<T> clazz) {
        try {
            return mapper.readValue(bytes, clazz);
        } catch (IOException e) {
            throw new RuntimeException("JSON字节反序列化失败", e);
        }
    }

    /**
     * 从输入流读取JSON转对象
     *
     * @param inputStream 输入流
     * @param clazz       目标类
     * @return 反序列化后的对象
     */
    public static <T> T parse(InputStream inputStream, Class<T> clazz) throws IOException {
        return mapper.readValue(inputStream, clazz);
    }

    /**
     * 从文件读取JSON转对象
     *
     * @param file  JSON文件
     * @param clazz 目标类
     * @return 反序列化后的对象
     */
    public static <T> T parse(File file, Class<T> clazz) throws IOException {
        return mapper.readValue(file, clazz);
    }

    /**
     * 处理泛型类型的反序列化
     *
     * @param json          JSON字符串
     * @param typeReference 类型引用（用于处理泛型）
     * @return 反序列化后的对象
     */
    public static <T> T parse(String json, TypeReference<T> typeReference) {
        try {
            return mapper.readValue(json, typeReference);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("泛型JSON反序列化失败", e);
        }
    }

    /* JSON树模型方法组 */

    /**
     * 将JSON字符串转为JsonNode
     *
     * @param json JSON字符串
     * @return JsonNode对象
     */
    public static JsonNode toJsonNode(String json) {
        try {
            return mapper.readTree(json);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON转树节点失败", e);
        }
    }

    /**
     * 将对象转为JsonNode
     *
     * @param object 要转换的对象
     * @return JsonNode对象
     */
    public static JsonNode toJsonNode(Object object) {
        return mapper.valueToTree(object);
    }

    /**
     * 从JsonNode转对象
     *
     * @param node  JsonNode节点
     * @param clazz 目标类
     * @return 反序列化后的对象
     */
    public static <T> T fromJsonNode(JsonNode node, Class<T> clazz) {
        try {
            return mapper.treeToValue(node, clazz);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JsonNode转对象失败", e);
        }
    }

    /* 高级操作 */

    /**
     * 对象转换（深拷贝）
     *
     * @param source     源对象
     * @param targetType 目标类型
     * @return 转换后的新对象
     */
    public static <T> T convert(Object source, Class<T> targetType) {
        return mapper.convertValue(source, targetType);
    }

    /**
     * 对象转换（深拷贝）
     *
     * @param source        源对象
     * @param typeReference 目标类型
     * @return 转换后的新对象
     */
    public static <T> T convert(Object source, TypeReference<T> typeReference) {
        return mapper.convertValue(source, typeReference);
    }

    /**
     * 更新对象（合并JSON）
     *
     * @param original 原始对象
     * @param json     包含更新字段的JSON字符串
     * @return 更新后的对象
     */
    public static <T> T update(T original, String json) throws IOException {
        return mapper.readerForUpdating(original).readValue(json);
    }

    /**
     * 克隆对象（深拷贝）
     *
     * @param object 要克隆的对象
     * @return 新的克隆对象
     */
    public static <T> T clone(T object) {
        return convert(object, (Class<T>) object.getClass());
    }

}
